#include "commerrno.h"
#include "CBattleMap.h"
#include "CBattleInf.h"
#include "CBattleData.h"
#include "CBattleRole.h"
#include "CBattleVideo.h"

/************************************************************************/
/*                          CGridMulti                                  */
/************************************************************************/
int CGridMulti::LeaveGrid(int iRoleID, CGridUnit& stGridUnit)
{
    for (int i = 0; i < _astGridMulti.Size(); ++i)
    {
        if (iRoleID == _astGridMulti[i].GetRoleID())
        {
            stGridUnit = _astGridMulti[i];
            _astGridMulti.DelOneItem(i);
            return 0;
        }
    }

    return ERROR_MOVE_FROM_NO_ROLE;
}

int CGridMulti::GotoGrid(CGridUnit& stGridUnit)
{
   if (_astGridMulti.Size() >= _astGridMulti.GetCount())
   {
       return ERROR_MOVE_TO_TOO_MANY_ROLES;
   }
    
   _astGridMulti.AddOneItem(stGridUnit);

   return 0;
}

int CGridMulti::GetGridMultiRoles(MAP_GRID_MULTI& stMapGridMulti)
{
    int iRoleID = 0;
    for (int i = 0; i < _astGridMulti.Size(); ++i)
    {
        iRoleID = _astGridMulti[i].GetRoleID();
        if (!BATTLE_INF->_pstRoles->IsValidRoleID(iRoleID))
        {
            CT_ERROR(("map role(%d) error!",iRoleID));
            continue;
        }
        CBattleRole& stRole = BATTLE_INF->_pstRoles->GetRole(iRoleID);
        if (!stRole.HasDead())
        {
            stMapGridMulti.AddOneItem(_astGridMulti[i]);
        }
    }

    return 0;
}

int CGridMulti::GetGridMultiSideRoles(MAP_GRID_MULTI& stMapGridMulti,
        bool bLeftSide)
{
    int iRoleID = 0;
    for (int i = 0; i < _astGridMulti.Size(); ++i)
    {
        iRoleID = _astGridMulti[i].GetRoleID();
        if (!BATTLE_INF->_pstRoles->IsValidRoleID(iRoleID))
        {
            CT_ERROR(("map role(%d) error!",iRoleID));
            continue;
        }
        CBattleRole& stRole = BATTLE_INF->_pstRoles->GetRole(iRoleID);
        if (!stRole.HasDead() && bLeftSide == stRole.IsLeft())
        {
            stMapGridMulti.AddOneItem(_astGridMulti[i]);
        }
    }

    return 0;
}

int CGridMulti::GetGridMultiCareerRoles(MAP_GRID_MULTI& stMapGridMulti,
        unsigned char ucCareer)
{
    int iRoleID = 0;
    for (int i = 0; i < _astGridMulti.Size(); ++i)
    {
        iRoleID = _astGridMulti[i].GetRoleID();
        if (!BATTLE_INF->_pstRoles->IsValidRoleID(iRoleID))
        {
            CT_ERROR(("map role(%d) error!",iRoleID));
            continue;
        }
        CBattleRole& stRole = BATTLE_INF->_pstRoles->GetRole(iRoleID);
        if (!stRole.HasDead() && ucCareer == stRole.GetCareer())
        {
            stMapGridMulti.AddOneItem(_astGridMulti[i]);
        }
    }

    return 0;
}

int CGridMulti::GetGridMultiPlayer(MAP_GRID_MULTI& stMapGridMulti)
{
    int iRoleID = 0;
    for (int i = 0; i < _astGridMulti.Size(); ++i)
    {
        iRoleID = _astGridMulti[i].GetRoleID();
        if (!BATTLE_INF->_pstRoles->IsValidRoleID(iRoleID))
        {
            CT_ERROR(("map role(%d) error!",iRoleID));
            continue;
        }
        CBattleRole& stRole = BATTLE_INF->_pstRoles->GetRole(iRoleID);
        if (!stRole.HasDead() && stRole.IsPlayerObject())
        {
            stMapGridMulti.AddOneItem(_astGridMulti[i]);
        }
    }

    return 0;
}

int CGridMulti::GetGridMultiPartner(MAP_GRID_MULTI& stMapGridMulti)
{
    int iRoleID = 0;
    for (int i = 0; i < _astGridMulti.Size(); ++i)
    {
        iRoleID = _astGridMulti[i].GetRoleID();
        if (!BATTLE_INF->_pstRoles->IsValidRoleID(iRoleID))
        {
            CT_ERROR(("map role(%d) error!",iRoleID));
            continue;
        }
        CBattleRole& stRole = BATTLE_INF->_pstRoles->GetRole(iRoleID);
        if (!stRole.HasDead() && stRole.IsPartnerObject())
        {
            stMapGridMulti.AddOneItem(_astGridMulti[i]);
        }
    }

    return 0;
}

bool CGridMulti::IsGridRoleAllDead()
{
    int iRoleID = 0;
    for (int i = 0; i < _astGridMulti.Size(); ++i)
    {
        iRoleID = _astGridMulti[i].GetRoleID();
        if (!BATTLE_INF->_pstRoles->IsValidRoleID(iRoleID))
        {
            CT_ERROR(("map role(%d) error!",iRoleID));
            continue;
        }
        CBattleRole& stRole = BATTLE_INF->_pstRoles->GetRole(iRoleID);
        if (!stRole.HasDead())
        {
            return false;
        }
    }
    
    return true;
}

/************************************************************************/
/*                          CMapSide                                    */
/************************************************************************/
//个体站位变动、个体死亡等事件都依赖下面接口重建边界
int CMapSide::ReCalcBorder()
{
    _iLeftFrontTo = -1;
    _iRightFrontTo = _astSideGrid.Size() - 1;

    for (int i = 0; i < _astSideGrid.Size(); ++i)
    {
        if (_astSideGrid[i].GetGridMultiSize() <= 0)
        {
            _astSideGrid[i].SetOwner(CGridMulti::BATTLE_GRID_OWNER_NONE);
        }
        else
        {
            //个体移动由CMapSide::Move接口保证阵营的同步
            if (_astSideGrid[i].IsGridRoleAllDead())
            {
                _astSideGrid[i].SetOwner(CGridMulti::BATTLE_GRID_OWNER_NONE);
            }
            else
            {
                if (CGridMulti::BATTLE_GRID_OWNER_LEFT == _astSideGrid[i].GetOwner())
                {
                    _iLeftFrontTo = i;
                }
                else if (CGridMulti::BATTLE_GRID_OWNER_RIGHT == _astSideGrid[i].GetOwner())
                {
                    if (_iRightFrontTo > i)
                    {
                        _iRightFrontTo = i;
                    }
                }
            }
        }
    }

    //左方后场要向下取整
    _iLeftBackTo = _iLeftFrontTo / 2;

    //右方后场要向上取整
    _iRightBackTo = (MAX_BATTLE_GRIDS + _iRightFrontTo) / 2;

    if (_iLeftFrontTo >= _iRightFrontTo || _iLeftBackTo < 0 || _iRightBackTo >= MAX_BATTLE_GRIDS)
    {
        CT_ERROR(("左方前场边界(%d)左方后场边界(%d)右方前场边界(%d)右方后场边界(%d)",
                    _iLeftFrontTo, _iLeftBackTo, _iRightFrontTo, _iRightBackTo));
        return ERROR_BATTLE_BORDER_RECALC;
    }

    return 0;
}

int CMapSide::InitMapSide(bool bLeftSide)
{
    _astSideGrid.m_iUsedCount = _astSideGrid.GetCount();
    for (int i = 0; i < _astSideGrid.Size(); ++i)
    {
        _astSideGrid[i].Clear();
    }

    CGridUnit stGridUnit;
    unsigned char ucOwner = CGridMulti::BATTLE_GRID_OWNER_NONE;
    int iPos = -1;

    for (int i = 0; i < BATTLE_INF->_pstRoles->GetRoleCount(); ++i)
    {
        CBattleRole& stRole = BATTLE_INF->_pstRoles->GetRole(i);
        stGridUnit.SetCareer(stRole.GetCareer());
        stGridUnit.SetOrder(stRole.GetAtkOrder());
        stGridUnit.SetRoleID(stRole.GetRoleID());

        //异或：两个操作数不相同时返回真
        if (bLeftSide^stRole.IsLeft())
        {
            ucOwner = CGridMulti::BATTLE_GRID_OWNER_RIGHT;
            iPos = MAX_BATTLE_GRIDS - 1 - stRole.GetOriginalPos();
        }
        else
        {
            ucOwner = CGridMulti::BATTLE_GRID_OWNER_LEFT;
            iPos = stRole.GetOriginalPos();
        }

        _astSideGrid[iPos].SetOwner(ucOwner);
        _astSideGrid[iPos].GotoGrid(stGridUnit);
    }

    return ReCalcBorder();
}

//需要调用层保证个体从iFrom到iTo都是合理的
int CMapSide::Move(int iRoleID, int iFrom, int iTo)
{
    int iRet = 0;
    CGridUnit stGridUnit;
    unsigned char ucOwner = _astSideGrid[iFrom].GetOwner();

    iRet = _astSideGrid[iFrom].LeaveGrid(iRoleID, stGridUnit);
    CT_RETURN(iRet);

    iRet = _astSideGrid[iTo].GotoGrid(stGridUnit);
    CT_RETURN(iRet);

    if (CGridMulti::BATTLE_GRID_OWNER_NONE == _astSideGrid[iTo].GetOwner())
    {
        _astSideGrid[iTo].SetOwner(ucOwner);
    }

    return ReCalcBorder();
}

unsigned char CMapSide::GetGridOwner(int iPos)
{
    if (!IsValidPos(iPos))
    {
        return CGridMulti::BATTLE_GRID_OWNER_NONE;
    }

    return _astSideGrid[iPos].GetOwner();
}

int CMapSide::GetDistanceRoles(int iSrcPos, int iDstPos,
        MAP_GRID_MULTI& stMapGridMulti)
{
    stMapGridMulti.Clear();

    if (!IsValidPos(iSrcPos) || !IsValidPos(iDstPos))
    {
        return ERROR_BATTLE_GRID_ID;
    }

    if (iSrcPos > iDstPos)
    {
        int iTmp = iSrcPos;
        iSrcPos = iDstPos;
        iDstPos = iTmp;
    }

    for (int i = iSrcPos; i <= iDstPos; ++i)
    {
        if (_astSideGrid[i].GetGridMultiSize() > 0)
        {
            _astSideGrid[i].GetGridMultiRoles(stMapGridMulti);
        }
    }

    return 0;
}

int CMapSide::GetDistanceSideRoles(int iSrcPos, int iDstPos,
        MAP_GRID_MULTI& stMapGridMulti, bool bLeftSide)
{
    stMapGridMulti.Clear();

    if (!IsValidPos(iSrcPos) || !IsValidPos(iDstPos))
    {
        return ERROR_BATTLE_GRID_ID;
    }

    if (iSrcPos > iDstPos)
    {
        int iTmp = iSrcPos;
        iSrcPos = iDstPos;
        iDstPos = iTmp;
    }

    for (int i = iSrcPos; i <= iDstPos; ++i)
    {
        if (_astSideGrid[i].GetGridMultiSize() > 0)
        {
            _astSideGrid[i].GetGridMultiSideRoles(stMapGridMulti, bLeftSide);
        }
    }

    return 0;
}

int CMapSide::GetDistanceCareerRoles(int iSrcPos, int iDstPos,
        MAP_GRID_MULTI& stMapGridMulti, unsigned char ucCareer)
{
    stMapGridMulti.Clear();

    if (!IsValidPos(iSrcPos) || !IsValidPos(iDstPos))
    {
        return ERROR_BATTLE_GRID_ID;
    }

    if (iSrcPos > iDstPos)
    {
        int iTmp = iSrcPos;
        iSrcPos = iDstPos;
        iDstPos = iTmp;
    }

    for (int i = iSrcPos; i <= iDstPos; ++i)
    {
        if (_astSideGrid[i].GetGridMultiSize() > 0)
        {
            _astSideGrid[i].GetGridMultiCareerRoles(stMapGridMulti, ucCareer);
        }
    }

    return 0;
}

int CMapSide::GetDistancePlayer(int iSrcPos, int iDstPos,
        MAP_GRID_MULTI& stMapGridMulti)
{
    stMapGridMulti.Clear();

    if (!IsValidPos(iSrcPos) || !IsValidPos(iDstPos))
    {
        return ERROR_BATTLE_GRID_ID;
    }

    if (iSrcPos > iDstPos)
    {
        int iTmp = iSrcPos;
        iSrcPos = iDstPos;
        iDstPos = iTmp;
    }

    for (int i = iSrcPos; i <= iDstPos; ++i)
    {
        if (_astSideGrid[i].GetGridMultiSize() > 0)
        {
            _astSideGrid[i].GetGridMultiPlayer(stMapGridMulti);
        }
    }

    return 0;
}

int CMapSide::GetDistancePartner(int iSrcPos, int iDstPos,
        MAP_GRID_MULTI& stMapGridMulti)
{
    stMapGridMulti.Clear();

    if (!IsValidPos(iSrcPos) || !IsValidPos(iDstPos))
    {
        return ERROR_BATTLE_GRID_ID;
    }

    if (iSrcPos > iDstPos)
    {
        int iTmp = iSrcPos;
        iSrcPos = iDstPos;
        iDstPos = iTmp;
    }

    for (int i = iSrcPos; i <= iDstPos; ++i)
    {
        if (_astSideGrid[i].GetGridMultiSize() > 0)
        {
            _astSideGrid[i].GetGridMultiPartner(stMapGridMulti);
        }
    }

    return 0;
}

/************************************************************************/
/*                          CBattleMap                                  */
/************************************************************************/
int CBattleMap::ReCalcBorder()
{
    int iRet = _stLeftSide.ReCalcBorder();
    CT_RETURN(iRet);

    iRet = _stRightSide.ReCalcBorder();
    CT_RETURN(iRet);

    return 0;
}

int CBattleMap::InitBattleMap()
{
#ifdef _DEBUG
    //打印一下所有角色信息
    BATTLE_INF->_pstRoles->DumpRolesInfo();
#endif

    int iRet = _stLeftSide.InitMapSide(true);
    CT_RETURN(iRet);

    iRet = _stRightSide.InitMapSide(false);
    CT_RETURN(iRet);

    return 0;
}

int CBattleMap::MoveTo(int iRoleID, int iFrom, int iTo, bool bLeftSide,
        bool bNeedRecord)
{
    if (!BATTLE_INF->_pstRoles->IsValidRoleID(iRoleID))
    {
        CT_ERROR(("map role(%d) error!",iRoleID));
        return 0;
    }

    int iRet = 0;
    
    CT_BATTLE(("角色(%d)在地图(1左:0右 %d)从格子(%d)到格子(%d)",iRoleID,
        bLeftSide,iFrom,iTo));

    if (!IsValidPos(iFrom) || !IsValidPos(iTo))
    {
        return ERROR_BATTLE_GRID_ID;
    }

    if (iFrom == iTo)
    {
        return 0;
    }

    CMapSide& stMapSide = bLeftSide ? _stLeftSide : _stRightSide;
    CMapSide& stOtherSide = bLeftSide ? _stRightSide : _stLeftSide;
    
    unsigned char ucSrcOwner = stMapSide.GetGridOwner(iFrom);
    if (ucSrcOwner == CGridMulti::BATTLE_GRID_OWNER_NONE)
    {
        return ERROR_MOVE_FROM_NO_OWNER_GRID;
    }

    unsigned char ucDstOwner = stMapSide.GetGridOwner(iTo);
    if (ucDstOwner != CGridMulti::BATTLE_GRID_OWNER_NONE &&
            ucDstOwner != ucSrcOwner)
    {
        CT_BATTLE(("角色(%d)从阵营(%d)到阵营(%d)",
            iRoleID,ucSrcOwner,ucDstOwner));
        return ERROR_MOVE_TO_GIRD_NOT_YOURS;
    }

    if (iTo >= stMapSide.GetRightFrontTo())
    {
        CT_BATTLE(("角色(%d)目标站位(%d)超越对方前场边界(%d)",
            iRoleID,iTo,stMapSide.GetRightFrontTo()));
        return ERROR_MOVE_TO_GIRD_NOT_YOURS;
    }

    iRet = stMapSide.Move(iRoleID, iFrom, iTo);
    CT_RETURN(iRet);

    iRet = stOtherSide.Move(iRoleID, MAX_BATTLE_GRIDS - 1 - iFrom,
        MAX_BATTLE_GRIDS - 1 - iTo);
    CT_RETURN(iRet);

    CBattleRole& stRole = BATTLE_INF->_pstRoles->GetRole(iRoleID);

    stRole.SetGridIndex((bLeftSide ? iTo : MAX_BATTLE_GRIDS - 1 - iTo));

    if (bNeedRecord)
    {
        BATTLE_INF->_pstVideo->Move(iRoleID, stRole.GetGridIndex());
    }

    return 0;
}

